package com.suray.wcs.service.test.action;

import com.suray.basic.wcs.path.enums.DirectionStatus;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.wcs.res.enums.PalletStatus;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.rescontact.ToRes;
import com.suray.wcs.service.test.base.BaseThread;
import com.suray.wcs.service.test.type.ActionTestType;
import com.suray.wcs.service.test.type.TestTaskProcess;

import java.util.HashMap;
import java.util.Map;

/**
 * 动作循环测试
 * 托盘，换向
 */
public class ActionCycleTask extends BaseThread {
    /**
     * 所有小车的动作循环任务
     */
    private static Map<Rgv, ActionCycleTask> actions = new HashMap<>();

    /**
     * 目标小车
     */
    private Rgv rgv;

    /**
     * 动作
     */
    private ActionTestType action;

    /**
     * 上次动作结束后托盘状态
     */
    private PalletStatus lastPalletStatus;

    /**
     * 上次动作结束后换向状态
     * 13巷道，24坡道
     */
    private DirectionStatus lastDirectionStatus;

    /**
     * 执行进度
     */
    private TestTaskProcess process;

    private ToRes toRes;

    public ActionCycleTask(Rgv rgv, ActionTestType action) {
        super("动作循环测试", 1000);

        this.rgv = rgv;
        this.action = action;

        toRes = ToRes.getInstance(rgv);

        lastPalletStatus = rgv.getPalletStatus();
        lastDirectionStatus = rgv.getDirectionStatus();

        process = TestTaskProcess.INIT;

        actions.put(rgv, this);
    }

    /**
     * 小车当前是否有循环动作
     * @param rgv
     * @return
     */
    private static boolean isRgvHasAction(Rgv rgv) {
        if (actions.get(rgv) != null) {
            return true;
        }

        return false;
    }

    /**
     * 分析小车，如果已经有动作则删除动作，否则添加动作
     * @param rgv
     * @param action
     */
    public synchronized static void analyzeAction(Rgv rgv, ActionTestType action) {
        if (isRgvHasAction(rgv)) {
            ActionCycleTask actionCycleTask = actions.get(rgv);
            actionCycleTask.endThread();
            actions.remove(rgv);
            setRgvTaskInfo(rgv, action, false);
            return;
        }

        new ActionCycleTask(rgv, action).start();
        setRgvTaskInfo(rgv, action, true);
    }

    private static void setRgvTaskInfo(Rgv rgv, ActionTestType action, boolean actionStatus) {
        switch (action) {
            case DIRECTION_ACTION:
                rgv.setReversLoop(actionStatus);
                break;
            case PALLET_ACTION:
                rgv.setPalletLoop(actionStatus);
                break;
            default:
                break;
        }
    }

    @Override
    protected void process() {
        if (action == ActionTestType.PALLET_ACTION) {
            rgv.setPalletLoop(true);
            palletAction();
        } else if (action == ActionTestType.DIRECTION_ACTION) {
            directionAction();
        } else {
            throw new RuntimeException("小车循环动作错误:" + action);
        }
    }

    /**
     * 小车托盘动作循环
     */
    private void palletAction() {
        switch (process) {
            case INIT:
                if (lastPalletStatus == PalletStatus.UP) {
                    process = TestTaskProcess.SECOND_TASK;
                } else {
                    process = TestTaskProcess.FIRST_TASK;
                }
                break;
            case FIRST_TASK:
                toRes.palletUp(null);
                lastPalletStatus = PalletStatus.UP;
                process = TestTaskProcess.WAIT_FIRST_TASK_END;
                break;
            case WAIT_FIRST_TASK_END:
                if (lastPalletStatus == PalletStatus.UP) {
                    LoggerUtil.info(rgv.getRgvName() + "小车托盘顶升成功", this.getClass());
                    process = TestTaskProcess.SECOND_TASK;
                }
                break;
            case SECOND_TASK:
                toRes.palletDown(null);
                lastPalletStatus = PalletStatus.DOWN;
                process = TestTaskProcess.WAIT_SECOND_TASK_END;
                break;
            case WAIT_SECOND_TASK_END:
                if (lastPalletStatus == PalletStatus.DOWN) {
                    LoggerUtil.info(rgv.getRgvName() + "小车托盘下降成功", this.getClass());
                    process = TestTaskProcess.FIRST_TASK;
                }
                break;
            case END:
            default:
                throw new RuntimeException("状态错误：" + toString());
        }
    }

    /**
     * 小车换向动作循环
     */
    private void directionAction() {
        switch (process) {
            case INIT:
                if (lastDirectionStatus == DirectionStatus.XD_13) {
                    process = TestTaskProcess.SECOND_TASK;
                } else {
                    process = TestTaskProcess.FIRST_TASK;
                }
                break;
            case FIRST_TASK:
                toRes.changeToRoadway(null);
                lastDirectionStatus = DirectionStatus.XD_13;
                process = TestTaskProcess.WAIT_FIRST_TASK_END;
                break;
            case WAIT_FIRST_TASK_END:
                if (lastDirectionStatus == DirectionStatus.XD_13) {
                    LoggerUtil.info(rgv.getRgvName() + "小车换向巷道成功", this.getClass());
                    process = TestTaskProcess.SECOND_TASK;
                }
                break;
            case SECOND_TASK:
                toRes.changeToRamp(null);
                lastDirectionStatus = DirectionStatus.PD_24;
                process = TestTaskProcess.WAIT_SECOND_TASK_END;
                break;
            case WAIT_SECOND_TASK_END:
                if (lastDirectionStatus == DirectionStatus.PD_24) {
                    LoggerUtil.info(rgv.getRgvName() + "小车换向坡道成功", this.getClass());
                    process = TestTaskProcess.FIRST_TASK;
                }
                break;
            case END:
            default:
                throw new RuntimeException("状态错误：" + toString());
        }
    }

    @Override
    public String toString() {
        return "ActionCycleTask{" +
                "rgv=" + rgv +
                ", action=" + action +
                ", lastPalletStatus=" + lastPalletStatus +
                ", process=" + process +
                '}';
    }
}
